#include "stdafx.h"

HistoryList::HistoryList()
{
	pCurrent = pRear;
	isMostPrevious = true;
	isMostEnd = true;
}

void HistoryList::Record(Command* objCommand)
{
	// If the current position is at the rear, 
	// just append the Command to the end of the queue
	if (pCurrent == pRear)
	{
		// If the queue is full, 
		// delete the most previous Command first,
		// then add the new one
		if (iCount == MAX_ITEM)
			Serve();
	}	
	else
	{
		// Otherwise, which means the current position is at the middle,
		// all Command at post-position to current must be clear.
		// ( This might happen when a user undo a few steps first,
		//   and make some other operations afterwards. )
		Cut(pCurrent);
	}
	Append(objCommand);
	isMostPrevious = false;
	isMostEnd = true;
	pCurrent = pRear;
}

/********************************************
* Cut from the pCutPost
* all element that to the post-position of pCutPost will be deleted,
* the element exact pointed by pCutPost will be remained.
******/
void HistoryList::Cut(DoubleLinkedNode<Command*>* pCutPost)
{
	// Delete from the rear
	DoubleLinkedNode<Command*>* pDel = pRear;
	while (pDel != pCutPost)
	{
		pDel = pDel->pPrevious;
		delete pDel->pNext;
		pDel-> pNext = 0;
		pRear = pDel;
		iCount--;
	}
}

/*******************************************
 * pCurrent is always points to a certain Command
 * However, in the logic of History
 * pCurrent indecates that current Command is executed
 ****/
void HistoryList::Undo()
{
	if (isMostPrevious)
		return;

	(pCurrent->pMainField)->UnExecute();
	isMostEnd = false;

	if(pCurrent == pFront)
	{
		isMostPrevious = true;
		return;
	}
	pCurrent = pCurrent->pPrevious;
}

void HistoryList::Redo()
{
	if(isMostEnd)
		return;
	if (!isMostPrevious)
		pCurrent = pCurrent->pNext;
	(pCurrent->pMainField)->Execute();
	isMostPrevious = false;
	if (pCurrent == pRear)
	{
		isMostEnd = true;
		return;
	}
}